namespace SupwinMatrix 
{   

    public class BasicTemplateAlgorithm : QCAlgorithm
    {
        //Initialize the data and resolution you require for your strategy:
		public int [] normalx={2,15,30,60};
		public int [] normaly={10,30,60,90};
		public int [] normalweight={500,300,200,100};
		public int [] restartweight={100,300,500,200};
		public int emafastp=5;
		public int emaslowp=30;
		public int probemarketp=30;
		public int reprobemarketp=10;
		public int probestockp=5;
		public decimal probemarketk=1.3;
		public decimal reprobemarketk=1;
		public decimal proberestartk=1;
		public decimal probestockk=1;
		public int restartsmap=30;
		public int mosthold=15;
		public int nowhold=0;
		public bool restart1=false;
		public bool restart2=false;
		public bool normal=true;
		public string mark="000300.SH";
		public decimal eachcash=0;
		public Dictionary<string,ExponentialMovingAverage> emafast=new Dictionary<string,ExponentialMovingAverage>();
		public Dictionary<string,ExponentialMovingAverage> emaslow=new Dictionary<string,ExponentialMovingAverage>();
		public Dictionary<string,SimpleMovingAverage> smafast1=new Dictionary<string,SimpleMovingAverage>();
		public Dictionary<string,SimpleMovingAverage> smafast2=new Dictionary<string,SimpleMovingAverage>();
		public Dictionary<string,SimpleMovingAverage> smafast3=new Dictionary<string,SimpleMovingAverage>();
		public Dictionary<string,SimpleMovingAverage> smafast4=new Dictionary<string,SimpleMovingAverage>();
		public Dictionary<string,SimpleMovingAverage> smaslow1=new Dictionary<string,SimpleMovingAverage>();
		public Dictionary<string,SimpleMovingAverage> smaslow2=new Dictionary<string,SimpleMovingAverage>();
		public Dictionary<string,SimpleMovingAverage> smaslow3=new Dictionary<string,SimpleMovingAverage>();
		public Dictionary<string,SimpleMovingAverage> smaslow4=new Dictionary<string,SimpleMovingAverage>();
		public Dictionary<string,BollingerBands> bbstock=new Dictionary<string,BollingerBands>();
		public Dictionary<string,decimal> score=new Dictionary<string,decimal>();
		public Dictionary<string,decimal>stopline=new Dictionary<string,decimal>();
        public override void Initialize() 
        {
			
            //Start and End Date range for the backtest:
            SetStartDate(2013, 1, 1);         
            SetEndDate(DateTime.Now.Date.AddDays(-1));
            //universe=hs300;
            //Cash allocation
            SetCash(100000);
            string [] universe={"000300.SH","000001.SZ", "000002.SZ", "000009.SZ", "000039.SZ", "000060.SZ", "000061.SZ", "000063.SZ", "000069.SZ", "000157.SZ", "000402.SZ", "000425.SZ", "000568.SZ", "000625.SZ", "000630.SZ", "000651.SZ", "000709.SZ", "000729.SZ", "000778.SZ", "000792.SZ", "000800.SZ", "000858.SZ", "000937.SZ", "000983.SZ", "600000.SH", "600009.SH", "600010.SH", "600015.SH", "600016.SH", "600019.SH", "600028.SH", "600029.SH", "600030.SH", "600031.SH", "600036.SH", "600050.SH", "600085.SH", "600100.SH", "600104.SH", "600153.SH", "600170.SH", "600177.SH", "600188.SH", "600196.SH", "600221.SH", "600256.SH", "600309.SH", "600362.SH", "600519.SH", "600583.SH", "600585.SH", "600600.SH", "600642.SH", "600649.SH", "600660.SH", "600690.SH", "600739.SH", "600741.SH", "600795.SH", "600839.SH", "600900.SH", "000538.SZ", "002024.SZ", "000768.SZ", "600383.SH", "600271.SH", "600415.SH", "600549.SH", "600875.SH", "601988.SH", "601006.SH", "601398.SH", "600048.SH", "600066.SH", "600068.SH", "600118.SH", "600150.SH", "600489.SH", "600547.SH", "601111.SH", "601628.SH", "601166.SH", "601318.SH", "601600.SH", "601998.SH", "601328.SH", "000876.SZ", "600208.SH", "600837.SH", "601333.SH", "601699.SH", "601088.SH", "601857.SH", "000338.SZ", "000423.SZ", "000895.SZ", "002142.SZ", "600089.SH", "600109.SH", "600111.SH", "601009.SH", "601169.SH", "601808.SH", "000686.SZ", "000728.SZ", "000783.SZ", "002202.SZ", "600804.SH", "601390.SH", "601601.SH", "601866.SH", "601898.SH", "601939.SH", "000100.SZ", "000623.SZ", "600588.SH", "600674.SH", "601186.SH", "601899.SH", "601958.SH", "000999.SZ", "600352.SH", "600518.SH", "600718.SH", "601766.SH", "002007.SZ", "600166.SH", "600369.SH", "601618.SH", "601668.SH", "002304.SZ", "600863.SH", "600999.SH", "601117.SH", "601607.SH", "601688.SH", "601888.SH", "601989.SH", "601288.SH", "000776.SZ", "002146.SZ", "002385.SZ", "002399.SZ", "002415.SZ", "002422.SZ", "600115.SH", "600276.SH", "600406.SH", "600535.SH", "600703.SH", "600887.SH", "600893.SH", "601158.SH", "601818.SH", "002500.SZ", "601018.SH", "601098.SH", "601118.SH", "601377.SH", "601933.SH", "000581.SZ", "000629.SZ", "002038.SZ", "002594.SZ", "600252.SH", "600372.SH", "600783.SH", "600873.SH", "601258.SH", "601992.SH", "000725.SZ", "002081.SZ", "002241.SZ", "002353.SZ", "600011.SH", "600315.SH", "600827.SH", "601336.SH", "601555.SH", "601633.SH", "601669.SH", "601901.SH", "601928.SH", "000750.SZ", "002236.SZ", "002375.SZ", "002673.SZ", "600027.SH", "600157.SH", "600340.SH", "600637.SH", "600886.SH", "601800.SH", "000156.SZ", "000963.SZ", "002294.SZ", "002450.SZ", "600060.SH", "600332.SH", "603993.SH", "000333.SZ", "000400.SZ", "000598.SZ", "000793.SZ", "000826.SZ", "000831.SZ", "002065.SZ", "002129.SZ", "002230.SZ", "002456.SZ", "600008.SH", "600018.SH", "600648.SH", "600663.SH", "600688.SH", "600705.SH", "601231.SH", "603000.SH", "000027.SZ", "000413.SZ", "000503.SZ", "000883.SZ", "000917.SZ", "002008.SZ", "002252.SZ", "002292.SZ", "002410.SZ", "002465.SZ", "002470.SZ", "002475.SZ", "600023.SH", "600633.SH", "600867.SH", "600998.SH", "601179.SH", "601216.SH", "601225.SH", "000559.SZ", "000825.SZ", "000898.SZ", "002153.SZ", "300015.SZ", "300017.SZ", "300024.SZ", "300027.SZ", "300058.SZ", "300070.SZ", "300124.SZ", "300133.SZ", "300146.SZ", "300251.SZ", "600038.SH", "600373.SH", "600398.SH", "600485.SH", "600570.SH", "600578.SH", "601727.SH", "603288.SH", "000166.SZ", "000738.SZ", "300003.SZ", "000046.SZ", "000539.SZ", "000712.SZ", "002736.SZ", "300002.SZ", "300059.SZ", "300104.SZ", "600005.SH", "600317.SH", "600717.SH", "600958.SH", "601021.SH", "601099.SH", "601106.SH", "601788.SH", "601919.SH", "601969.SH", "601991.SH", "000415.SZ", "000540.SZ", "002195.SZ", "002739.SZ", "300144.SZ", "300315.SZ", "600021.SH", "600350.SH", "600820.SH", "600895.SH", "600959.SH", "601016.SH", "601198.SH", "601211.SH", "601238.SH", "601608.SH", "601718.SH", "601872.SH", "601985.SH", "603885.SH", "001979.SZ"};
            //Add as many securities as you like. All the data will be passed into the event handler:
			foreach (string stock in universe)
			{
				AddSecurity(SecurityType.Equity, stock, Resolution.Daily, "cn", true, 0, false);
				smafast1[stock]=SMA(stock,normalx[0]);
				smafast2[stock]=SMA(stock,normalx[1]);
				smafast3[stock]=SMA(stock,normalx[2]);
				smafast4[stock]=SMA(stock,normalx[3]);
				smaslow1[stock]=SMA(stock,normaly[0]);
				smaslow2[stock]=SMA(stock,normaly[1]);
				smaslow3[stock]=SMA(stock,normaly[2]);
				smaslow4[stock]=SMA(stock,normaly[3]);
				emafast[stock]=EMA(stock,emafastp);
				emaslow[stock]=EMA(stock,emaslowp);
				bbstock[stock]=BB(stock,probestockp,probestockk);
			}
			var restartsma=SMA(mark,restartsmap);
			var marketbb=BB(mark,probemarketp,probemarketk);
			var remarketbb=BB(mark,reprobemarketp,reprobemarketk)
            SetBenchmark(mark);
        }

        //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
        public void OnData(TradeBars data) 
        {   
		    //判断是否进入异常的状态
			if(data[mark].Price<=marketbb.LowerBand)
			{
				Liquidate();
				restart1=true;
				restart2=false;
				normal=false;
			}
			//判断是否进入异常的状态
			//止损代码
			foreach(string stock in stopline.Keys)
			{
				if(Portfolio[stock].HoldStock)
				{
					if(stopline[stock]<((data[stock].Price+data[stock.Price])/2*0.9m))
					{
						stopline[stock]=(data[stock].Price+data[stock.Price])/2*0.9m;
					}
					if(stopline[stock]>=data[stock].Price) Liquidate(stock);
				}
			}
			//止损代码
            if(restart1)
			{
				if(data[mark]<restartsma)
					return;
				else
				{
					restrat1=false;
					restrat2=true;
					normal=false;
				}
			}
			
			//判断是否进入正常的状态
			if(data[mark].Price>=remarketbb.UpperBand)
				{
					restart2=false;
					normal=true;
				}
			//判断是否进入正常的状态
			if(restart2)
			{
				nowhold=0;
				foreach(string stock in universe)
				{
					if(Portfolio[stock].HoldStock) nowhold++;
					//如果在前面加了止损，那么nowhold就不用在这里弄
					if(smaslow1[stock]==0||smaslow2[stock]==0||smaslow3[stock]==0||smaslow4[stock]==0)	
					score[stock]=(smafast1[stock]-smaslow1[stock])*restartweight[0]/smaslow1[stock]+
					(smafast2[stock]-smaslow2[stock])*restartweight[1]/smaslow2[stock]+
					(smafast3[stock]-smaslow3[stock])*restartweight[2]/smaslow3[stock]+
					(smafast4[stock]-smaslow4[stock])*restartweight[3]/smaslow4[stock];
				}
				if(nowhold>=mosthold) return;
				else eachcash=Portfolio.Cash/(mosthold-nowhold);
				//排序score
				var score_dc=from obj in score orderby obj.Value descending select obj;
				foreach (KeyValuePair<string,decimal> i in score_dc)
				{
					if(nowhold>=mosthold) break;
					string stock=i.Key;
					if(data[stock].Price>=bbstock[stock].UpperBand&&!Portfolio[stock].HoldStock)
					{
						int value=(int)(eachcash/data[string].Price);
						Order(stock,value);
						nowhold++;
						stopline[stock]=(data[stock].Price+data[stock.Price])/2*0.9m;
					}
				}
				
			}
			if(normal)
			{
				nowhold=0;
				foreach(string stock in universe)
				{
					if(Portfolio[stock].HoldStock) nowhold++;
					//如果在前面加了止损，那么nowhold就不用在这里弄
					if(smaslow1[stock]==0||smaslow2[stock]==0||smaslow3[stock]==0||smaslow4[stock]==0)	
					score[stock]=(smafast1[stock]-smaslow1[stock])*marketweight[0]/smaslow1[stock]+
					(smafast2[stock]-smaslow2[stock])*marketweight[1]/smaslow2[stock]+
					(smafast3[stock]-smaslow3[stock])*marketweight[2]/smaslow3[stock]+
					(smafast4[stock]-smaslow4[stock])*marketweight[3]/smaslow4[stock];
				}
				if(nowhold>=mosthold) return;
				else eachcash=Portfolio.Cash/(mosthold-nowhold);
				//排序score
				var score_dc=from obj in score orderby obj.Value descending select obj;
				foreach (KeyValuePair<string,decimal> i in score_dc&&!Portfolio[stock].HoldStock)
				{
					if(nowhold>=mosthold) break;
					string stock=i.Key;
					if(emafast[stock]>emaslow[stock])
					{
						int value=(int)(eachcash/data[string].Price);
						Order(stock,value);
						nowhold++;
						stopline[stock]=(data[stock].Price+data[stock.Price])/2*0.9m;
					}
				}
			}
			
        }
    }
}